package com.fanshilz.flower2025.framework.aop;

import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.fanshilz.flower2025.framework.exception.CodeException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

@Slf4j
@Aspect
@Component
public class WebLogAspect {

    private final ThreadLocal<Long> start = new ThreadLocal<>();

    public static final ThreadLocal<String> requestURIThread = new ThreadLocal<>();

    @Pointcut("execution(public * com.fanshilz.flower2025.apps.*.*.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        start.set(System.currentTimeMillis());

        // MDCInsertingServletFilter

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

//        Assert.notNull(attributes, () -> new RuntimeException(""));

        if (attributes == null) {
            throw new CodeException("attributes == null");
        }

        HttpServletRequest request = attributes.getRequest();

        String requestURI = request.getRequestURI();

        // /admin/user/current
//        log.info("requestURI = {}", requestURI);
        requestURIThread.set(requestURI);

        String requestURL = request.getRequestURL().toString();
//        MDC.put("req_url", requestURL);

        String method = request.getMethod();
//        MDC.put("http_method", method);

        String remoteAddr = request.getRemoteAddr();
//        MDC.put("remote_addr", remoteAddr);

        String xRealIp = request.getHeader("X-Real-IP");
//        MDC.put("real_ip", xRealIp);

        String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
//        MDC.put("class_method", classMethod);

        String args = Arrays.toString(joinPoint.getArgs());
//        MDC.put("args", args);

        log.info("request_url : {}, http_method : {}, remote_addr : {}, real_ip : {}, class_method : {}, args : {}",
                requestURL, method, remoteAddr, xRealIp, classMethod, args);

    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {
        String res = JSONUtil.toJsonStr(ret, JSONConfig.create().setIgnoreNullValue(false));
//        MDC.put("resp", res);

        long time = (System.currentTimeMillis() - start.get());
        start.remove();

//        MDC.put("spend_time", String.valueOf(time));

        log.info("resp : {}, spend_time : {}", res, time);

        requestURIThread.remove();
    }

}


